package com.aizuda.easyManagerTool.service.server.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.aizuda.easy.security.domain.Rep;
import com.aizuda.easy.security.domain.Req;
import com.aizuda.easy.security.exp.impl.BasicException;
import com.aizuda.easyManagerTool.config.CiphertextTypeHandler;
import com.aizuda.easyManagerTool.domian.bo.PackagesBO;
import com.aizuda.easyManagerTool.domian.dto.PageDTO;
import com.aizuda.easyManagerTool.domian.entity.monitor.MonitorDataEntity;
import com.aizuda.easyManagerTool.domian.entity.server.ServerEntity;
import com.aizuda.easyManagerTool.domian.vo.PageVO;
import com.aizuda.easyManagerTool.domian.vo.server.ServerVO;
import com.aizuda.easyManagerTool.domian.vo.setting.SettingUserVO;
import com.aizuda.easyManagerTool.domian.vo.terminal.MonitorVO;
import com.aizuda.easyManagerTool.mapper.server.ServerMapper;
import com.aizuda.easyManagerTool.mapper.server.ServerPKMapper;
import com.aizuda.easyManagerTool.service.monitor.MonitorDataService;
import com.aizuda.easyManagerTool.service.server.ServerService;
import com.aizuda.easyManagerTool.service.setting.PackageCheckService;
import com.aizuda.easyManagerTool.service.terminal.MonitorTerminalService;
import com.aizuda.easyManagerTool.util.AssertUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service("server")
public class ServerServiceImpl extends ServiceImpl<ServerMapper, ServerEntity> implements ServerService, PackageCheckService {

    @Resource
    ServerMapper serverMapper;
    @Resource
    ServerPKMapper serverPKMapper;
    @Resource
    MonitorDataService monitorDataService;
    @Resource
    MonitorTerminalService monitorTerminalService;
    @Value("${config.intranet-ip}")
    private String intranetIp;

    @Value("${server.port}")
    private String port;

    @Override
    public Rep<PageVO<ServerVO>> find(Req<PageDTO<ServerEntity>, SettingUserVO> req) {
        PageDTO<ServerEntity> pageDTO = req.getData();
        Page<ServerEntity> page = new Page<ServerEntity>(pageDTO.getCurrent(), pageDTO.getSize());
        // 查询 唯一条件是要根据 权限查询
        ServerEntity server = pageDTO.getData() ;
        IPage<ServerVO> serverListEntrtyIPage = serverMapper.find(page,ObjectUtil.isEmpty(server)? new ServerEntity():server);
        PageVO<ServerVO> pageVO = new PageVO<ServerVO>(pageDTO)
                .setTotal(serverListEntrtyIPage.getTotal())
                .setRecords(serverListEntrtyIPage.getRecords());
        return Rep.ok(pageVO);
    }

    @Transactional
    @Override
    public Rep<ServerEntity> edit(Req<ServerEntity, SettingUserVO> req) {
        ServerEntity data = req.getData();
        SettingUserVO user = req.getUser();
        AssertUtil.objIsNull(data.getServerIp(), "IP不能为空");
        AssertUtil.objIsNull(data.getServerAccount(), "服务器账号不能为空");
        AssertUtil.objIsNull(data.getServerTypeId(), "类型不能为空");
        AssertUtil.objIsNull(data.getServerName(), "名称不能为空");
        String[] splitIP = data.getServerIp().split(";");
        if(splitIP.length > 1){
            return addOrUpdateManyData(data,user);
        }else{
            return addOrUpdateOneData(data,user);
        }
    }

    private Rep<ServerEntity> addOrUpdateManyData(ServerEntity data,SettingUserVO user) {
        String[] split = data.getServerIp().split(";");
        List<String> find = Arrays.stream(split).map(CiphertextTypeHandler::encrypt).collect(Collectors.toList());
        // 通过IP批量查询
        List<ServerEntity> serverEntities = serverMapper.findBatchIp(find);
        List<ServerEntity> serverIp = Arrays.stream(split).map(item -> {
            Optional<ServerEntity> any = serverEntities.stream().filter(ik -> ik.getServerIp().equals(item)).findAny();
            ServerEntity server = any.orElse(new ServerEntity());
            if (ObjectUtil.isNull(server.getId())) {
                BeanUtil.copyProperties(data, server, "serverIp","id");
                server.setServerIp(item);
            }
            server.setServerAccount(data.getServerAccount());
            server.setServerPassword(data.getServerPassword());
            return server;
        }).collect(Collectors.toList());
        saveOrUpdateBatch(serverIp);
        // 批量监控添加或修改
        serverIp.parallelStream().forEach(i -> {
            MonitorDataEntity monitorDataEntity = new MonitorDataEntity();
            monitorDataEntity.setTenantId(user.getTenantId());
            monitorDataEntity.setMdTitle(i.getServerName()+"-"+i.getServerIp());
            monitorDataEntity.setMdUrl(intranetIp+":"+port+"/server/monitor/"+i.getId());
            monitorDataService.edit(monitorDataEntity);
        });
        return Rep.ok();
    }


    private Rep<ServerEntity> addOrUpdateOneData(ServerEntity data,SettingUserVO user) {
        MonitorDataEntity monitorDataEntity = new MonitorDataEntity();
        monitorDataEntity.setMdTitle(data.getServerName()+"-"+data.getServerIp());
        monitorDataEntity.setTenantId(user.getTenantId());
        if(ObjectUtil.isNull(data.getId())){
            // 监控添加
            serverMapper.insert(data);
            monitorDataEntity.setMdUrl(intranetIp+":"+port+"/server/monitor/"+data.getId());
            monitorDataService.edit(monitorDataEntity);
            return Rep.ok(data);
        }
        // 监控修改
        ServerEntity byId = serverMapper.selectById(data.getId());
        monitorDataEntity.setMdUrl(intranetIp+":"+port+"/server/monitor/"+byId.getId());
        BeanUtil.copyProperties(data, byId, "id","createTime");
        serverMapper.updateById(byId);
        monitorDataService.edit(monitorDataEntity);
        return Rep.ok(byId);
    }

    @Transactional
    @Override
    public Rep<ServerEntity> del(Req<ServerEntity, SettingUserVO> req) {
        ServerEntity data = req.getData();
        AssertUtil.objIsNull(data.getId(), "id不能为空");
        serverMapper.delTrue(data.getId());
        serverPKMapper.deleteServerId(data.getId());
        monitorDataService.del(intranetIp+":"+port+"/server/monitor/"+data.getId(),req.getUser().getTenantId());
        return Rep.ok(data);
    }

    @Override
    public Rep<ServerEntity> findById(Req<ServerEntity, SettingUserVO> req) {
        ServerEntity data = req.getData();
        AssertUtil.objIsNull(data.getId(), "ID为空，数据错误");
        ServerEntity server = serverMapper.selectById(data.getId());
        return Rep.ok(server);
    }

    @Override
    public Rep<List<ServerEntity>> findAll(Req<ServerEntity, SettingUserVO> req) {
        List<ServerEntity> serverEntities = serverMapper.findAll();
        if(CollUtil.isEmpty(serverEntities)){
            serverEntities = new ArrayList<>();
        }
        return Rep.ok(serverEntities);
    }

    @Override
    public Object monitor(Integer id) {
        MonitorVO monitor = monitorTerminalService.monitor(id);
        return monitor;
    }

    @Override
    public void packageCheck(PackagesBO.Item item,Integer tenantId) throws BasicException {
        Integer num = serverMapper.findTotal(tenantId);
        if(num.compareTo(item.getNum()) >= 0){
            throw new BasicException(500,"当前套餐资源用完，请升级套餐");
        }
    }
}
